#include <REG_MPC82G516.H>
#include "uart.h"

/*
void DelaymSec(unsigned int count)
{
  unsigned int i;                      // for Keil PK51 (Speed x 12) 
  while (count) {
    i = 850; while (i>0) i--;
    count--;
  }
}
*/
#define SOH  0x01
#define STX  0x02
#define ETX  0x03
#define EOT  0x04
#define BEL  0x07
#define HXOR ('T' ^ 'X' ^ STX)

sbit PTT                = P1^0;
sbit NCD                = P1^1;
sbit RDIRU1             = P1^2;
sbit RDIRU2             = P1^3;
#define RID             = (P2&0x0F);
#define TX_BUFFER_MAX     768
#define RX_BUFFER_MAX     256
unsigned char xdata TxBUFF[TX_BUFFER_MAX];
unsigned int TxBUFFHead = 0;
unsigned int TxBUFFTail = 0;
unsigned int AtTx       = 0;
unsigned char xdata RxBUFF[RX_BUFFER_MAX];
unsigned int RxBUFFLen   = 0;
unsigned char AtRx       = 0;

void Reset(void)
{
  ((void(code *)(void))0x0000)();
}

void main()
{
  unsigned char Ch1, Ch2;
  unsigned int CD = 0;
  unsigned char XSUM = 0x00;
  unsigned char RSUM = 0x00;
  unsigned char InBEL = 0;
  
  UART1_Init(9600, 1);                 // UART1 9600 Interrupt
  UART2_Init(1200, 1);                 // UART2 1200 Interrupt
  
  P1 = 0xFF;                           // Initialize P2 Port
                                       // P2^7    = PTT (Push to talk)
                                       // P2^6    = NCD (No Radio Carier Detect)
                                       // P2^5    = Redirect UART1 <-> UART2
                                       // P2^0..3 = RID (Radio ID)
  
  while(1) {
    if(!NCD) {
      CD = 8000;
    }
    else {
      if(CD) CD--;
    }
    if(UART1_RxHead != UART1_RxTail) {
      Ch1 = UART1_RxBuffer[UART1_RxTail++];
      UART1_RxTail &= 0x1F;
      //if(!RDIRU1) {
      //  UART2_TxByte(Ch1);
      //  continue;
      //}
      TxBUFF[TxBUFFHead++] = Ch1;
      TxBUFFHead &= (TX_BUFFER_MAX - 1);
      if(TxBUFFHead == TxBUFFTail) {
        Reset();
      }
    }
    if(UART2_RxHead != UART2_RxTail) {
      Ch2 = UART2_RxBuffer[UART2_RxTail++];
      UART2_RxTail &= 0x1F;
      //if(!RDIRU2) {
      //  UART1_TxByte(Ch2);
      //  continue;
      //}
      CheckSOH:
      switch(AtRx) {
        case 0: {
          if(Ch2 == SOH) {
            AtRx = 1;
          }
          break;
        }
        case 1: {
          if(Ch2 == 'T') {
            AtRx = 2;
          }
          else {
            AtRx = 0;
            goto CheckSOH;
          }
          break;
        }
        case 2: {
          if(Ch2 == 'X') {
            AtRx = 3;
          }
          else {
            AtRx = 0;
            goto CheckSOH;
          }
          break;
        }
        case 3: {
          if(Ch2 == STX) {
            RSUM = HXOR;
            InBEL = 0;
            RxBUFFLen = 0;
            RxBUFF[0] = 0;
            AtRx = 4;
          }
          else {
            AtRx = 0;
            goto CheckSOH;
          }
          break;
        }
        case 4: {
          if(Ch2 == ETX) {
            RxBUFF[RxBUFFLen] = 0;
            RSUM ^= Ch2;
            AtRx = 5;
          }
          else if(Ch2 < BEL) {
            AtRx = 0;
            goto CheckSOH;
          }
          else if(Ch2 == BEL) {
            RSUM ^= Ch2;
            InBEL = 1;
          }
          else {
            if(InBEL) {
              RxBUFF[RxBUFFLen] = Ch2 - '0';
              InBEL = 0;
            }
            else {
              RxBUFF[RxBUFFLen] = Ch2;
            }
            RxBUFFLen++;
            if(RxBUFFLen >= RX_BUFFER_MAX) {
              Reset();
              AtRx = 0;
              goto CheckSOH;
            }
            RSUM ^= Ch2;
          }
          break;
        }
        case 5: {
          if(Ch2 == (RSUM & 0x0F) + '0') {
            AtRx = 6;
          }
          else {
            AtRx = 0;
            goto CheckSOH;
          }
          break;
        }
        case 6: {
          if(Ch2 == (RSUM >> 4) + '0') {
            AtRx = 7;
          }
          else {
            AtRx = 0;
            goto CheckSOH;
          }
          break;
        }
        case 7: {
          AtRx = 0;
          if(Ch2 == 0x04) {
            while(AtRx < RxBUFFLen) {
              UART1_TxByte(RxBUFF[AtRx++]);
            }
            AtRx = 0;
          }
          else {
            goto CheckSOH;
          }
          break;
        }
        default:  {
          Reset();
        }
      }
    }
    if((TxBUFFHead != TxBUFFTail) && (AtTx < 8000)) {
      if(AtTx == 0) {
        if(!CD) {
          PTT = 0;
          AtTx++;
          UART2_TxByte('\r');
          UART2_TxByte('\n');
        }
      }
      else if(AtTx >= 4000) {
        switch(AtTx-4000) {
          case 0: {
            UART2_TxByte(SOH);
            AtTx++;
            break;
          }
          case 1: {
            UART2_TxByte('T');
            AtTx++;
            break;
          }
          case 2: {
            UART2_TxByte('X');
            AtTx++;
            break;
          }
          case 3: {
            UART2_TxByte(STX);
            XSUM = HXOR;
            AtTx++;
            break;
          }
          default: {
            Ch1 = TxBUFF[TxBUFFTail++];
            TxBUFFTail &= (TX_BUFFER_MAX - 1);
            if(Ch1 > BEL) {
              UART2_TxByte(Ch1);
              XSUM ^= Ch1;
            }
            else {
              UART2_TxByte(BEL);
              XSUM ^= BEL;
              UART2_TxByte(Ch1 + '0');
              XSUM ^= (Ch1 + '0');
            }
            AtTx = 4000+4;
            break;
          }
        }
      }
      else {
        AtTx++;
      }
    }
    else {
      if(!AtTx) {
        PTT = 1;
      }
      else if(AtTx >= 8000) {
        switch(AtTx-8000) {
          case 0: {
            UART2_TxByte(ETX);
            XSUM ^= 0x03;
            AtTx++;
            break;
          }
          case 1: {
            UART2_TxByte((XSUM & 0x0F) + '0');
            AtTx++;
            break;
          }
          case 2: {
            UART2_TxByte((XSUM >> 4) + '0');
            AtTx++;
            break;
          }
          case 3: {
            UART2_TxByte(EOT);
            XSUM = 0x00;
            AtTx++;
            break;
          }
          case 4: {
            UART2_TxByte('\r');
            AtTx++;
            break;
          }
          case 5: {
            UART2_TxByte('\n');
            PTT = 1;
            AtTx = 0;
            break;
          }
        }
      }
      else {
        AtTx++;
      }
    }
  }
}
